#ifndef _ANTISYM_COEFF_
#define _ANTISYM_COEFF_
#include "../DF_Common/basis_state.h"
#include "../DF_Common/coupling_coeff.h"
#include "../DF_Common/progress_bar.h"
#include <cmath>
#include <eigen3/Eigen/Dense>
#include <eigen3/Eigen/SparseCore>
#include <stdlib.h>
#include <vector>
using Eigen::MatrixXd;
using Eigen::SelfAdjointEigenSolver;
using std::cout;
using std::endl;
using std::vector; 

class Antisym {
public:
  Antisym(SixJ_coeff &sixJ_t, NinJ_coeff &ninJ_t, Hobra &hobra_t,
          Jacobi &Jacobi_t)
      : sixJ(sixJ_t), ninJ(ninJ_t), hobra_x(hobra_t), Jacobi_x(Jacobi_t) {}
  SixJ_coeff &sixJ;
  NinJ_coeff &ninJ;
  Hobra &hobra_x;
  Jacobi &Jacobi_x;

  MatrixXd anti_mat;

  vector<vector<vector<double>>> eig_val;       // eig_val[channel][E][i]
  vector<vector<vector<vector<double>>>> vec_D; // vec_D[channel][E][i][j]
  vector<vector<double>> eig_num; // eig_num[channel][E] double to check the
                                  // completeness of Jacobi basis

  void cal();

  void cal(int channel, int E_min, int E_max) {
    // cout<<"antiysym mat build begin"<<endl;
    this->JTmat_build(Jacobi_x, channel, E_min, E_max);
    // cout<<"antiysym mat build end"<<endl;
    this->mat_diag();
  }

  // private:
  double mat_cal(State_Jacobi &finial_state, State_Jacobi &init_state);
  void JTmat_build(Jacobi &Jacobi_t, int channel_num);
  void JTmat_build(Jacobi &Jacobi_t, int channel_num, int E);
  void JTmat_build(Jacobi &Jacobi_t, int channel_num, int E_min, int E_max);
  void print(std::string filename);

private:
  int diag_flag = -1;
  int build_flag = -1;
  double anti_basis_num_d;
  vector<double> eig_val_t;
  int anti_basis_num;
  int cout_flag = -1;
  MatrixXd anti_vec_C;
  MatrixXd anti_vec_D;

  void mat_diag();

  void mark_Jaco(int channel, int E);
  int Tri(int &j2a, int &j2b, int &j2c);
  int Tri_state(State_Jacobi &state);
  int phase(int n);
};

#endif
